/*
 *	ME2 C++ SDK
 *	Copyright (c) 2010 _silencer
 *
 *	Permission is hereby granted, free of charge, to any person
 *	obtaining a copy of this software and associated documentation
 *	files (the "Software"), to deal in the Software without
 *	restriction, including without limitation the rights to use,
 *	copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following
 *	conditions:
 *
 *	The above copyright notice and this permission notice shall be
 *	included in all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *	OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef UNREAL_CLASS_H
#define UNREAL_CLASS_H

#include "unreal_base.h"
#include "unreal_state.h"
#include "unreal_property.h"

namespace unreal
{
	#pragma pack(push)
	#pragma pack(1)

	struct urep_record
	{
		uproperty* property;
		int32 index;
	};

	/*
		TODO write some dump code to check these flags from ut99 are still valid!
	 */
	enum uclass_flags
	{
		uclass_none					= 0x00000000,
		uclass_abstract				= 0x00000001,
		uclass_compiled				= 0x00000002,
		uclass_config				= 0x00000004,
		uclass_transient			= 0x00000008,
		uclass_parsed				= 0x00000010,
		uclass_localized			= 0x00000020,
		uclass_safe_replace			= 0x00000040,
		uclass_runtime_static		= 0x00000080,
		uclass_no_export			= 0x00000100,
		uclass_no_user_create		= 0x00000200,
		uclass_per_object_config	= 0x00000400,
		uclass_native_replication	= 0x00000800,
		uclass_unknown_0			= 0x00001000,
		uclass_unknown_1			= 0x00002000,
		uclass_isa_uproperty		= 0x00008000,
		uclass_isa_uobjectproperty	= 0x00010000,
		uclass_isa_uboolproperty	= 0x00020000,
		uclass_isa_ustate			= 0x00040000,
		uclass_isa_ufunction		= 0x00080000,
		uclass_unknown_2			= 0x00100000,
		uclass_unknown_3			= 0x00400000,
		uclass_unknown_4			= 0x00800000,
		uclass_unknown_5			= 0x01000000,
		uclass_unknown_6			= 0x02000000,
		uclass_unknown_7			= 0x04000000,

		uclass_inherit				= uclass_transient | uclass_config | uclass_localized | uclass_safe_replace | uclass_runtime_static | uclass_per_object_config,
		uclass_recompiler_clear		= uclass_inherit | uclass_abstract | uclass_no_export | uclass_native_replication
	};

	/*
		TODO more reverse engineering!
	 */
	class uclass: public ustate
	{
		DECLARE_CORE_CLASS( uclass, ustate, Class )

	public:

		uint32 get_class_flags() const
		{
			return class_flags_;
		}

		void set_class_flags( const uint32 class_flags )
		{
			class_flags_ = class_flags;
		}

	private:

		uint32 class_flags_;
		int32 class_unique_;
		uname class_config_name;
		uclass* class_within_;
		uguid class_guid_;
		uint32 unknown_0_;
		uarray<urep_record> class_reps_;
		uarray<ufield*> net_fields_;
		uarray<uint32> package_imports_;
		uarray<uint32> hide_categories_;
		uarray<uint32> auto_expand_categories_;
		uobject* default_;
		uarray<uint32> dependent_on_;
		uarray<char> class_header_filename_;
		//void (*ClassConstructor)(void*);
		//void (UnrealObject::*ClassStaticConstructor)();
		uclass* component_owner_class_;
		umap<uclass*, uname> component_class_to_name_map_;
		umap<uname, ucomponent*> component_name_to_default_object_map_;
		uarray<char> default_prop_text_;
		uarray<char> unknown_1_;
	};

	#pragma pack(pop)
}

#endif
